package com.base.lambda;

import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;

public class Main {

	public static void main(String[] args) {
		//https://blog.csdn.net/weixin_44799607/article/details/103780047
		//1.List存储对象取id 和name转成Map 集合
		test1();
		//2.List存储对象条件过滤遍历
		test2();
		//3.List存放string数据转为大小写
		test3();
		//4.获取List数据得到一个以逗号分隔的字符串
		test4();
		//5.List去重
		test5();
		//6.List存储int数据查找最大值最小值
		test6();
		//7.List集合获取int元素的平方
		test7();
		//8.List返回特定结果
		test8();
		//9.List对int类型数据进行排序
		test9();
		//10.List匹配规则
		test10();
		//11.List存储对象数据按条件进行分组
		test11();
		//12.流中的归约用法
		test12();
		//13.Java8 summaryStatijstics配合流使用
		test13();
		//14.Java8字符串转字符
		test14();
	}


	/**
	 * List存储对象取id 和name转成Map 集合
	 */
	private static void test1() {
		 //创建集合存储user对象
        List<UserInfo> userInfoList = new ArrayList<>();
        UserInfo user = new UserInfo();
        user.setUserId(1L);
        user.setRealName("张三");
        
        UserInfo user2 = new UserInfo();
        //user2.setUserId(2L);
        user2.setRealName("李四");
        
        userInfoList.add(user);
        userInfoList.add(user2);
        
        //使用Collectors.toMap记录:
        //问题1:key 和 value 不能为null --> 解决方案 增加过滤条件
        //问题2:key 不能重复,不然报错 -->解决方案 增加(oldValue,newValue) -> oldValue, HashMap::new)
        Map<Long, String> map = 
                  //创建一个并行流
                 userInfoList.parallelStream()
                  //添加过滤条件        
                .filter(u -> u != null 
                		&& u.getUserId() != null
                		&& u.getRealName() != null
                		)
                  //返回一个Map集合key是userId  value是用户姓名    
                .collect(Collectors.toMap(
                		UserInfo::getUserId, UserInfo::getRealName,
                		(oldValue,newValue) -> oldValue, HashMap::new));
        
        //遍历打印
        map.forEach((k,v)->{
        	System.out.println("key1:"+k+"  "+"value1: "+v);
        });
        
        //转map方式二 使用stream的collect的重载方法：
        map = userInfoList.stream().collect(HashMap::new, (m,v)->
        		m.put(v.getUserId(), v.getRealName()),HashMap::putAll);
        map.forEach((k,v)->{
        	System.out.println("key2:"+k+"  "+"value2: "+v);
        });
        
	}
	
	/**
	 * List存储对象条件过滤遍历
	 */
	private static void test2() {
		//创建集合存储user对象
        List<UserInfo> userInfoList = new ArrayList<>();
        UserInfo user = new UserInfo();
        user.setUserId(1L);
        user.setRealName("张三");
        userInfoList.add(user);
        
        UserInfo user2 = new UserInfo();
        user2.setUserId(2L);
        user2.setRealName("李四");
        userInfoList.add(user2);
        
        //判断集合是否为空
        Optional.ofNullable(userInfoList)
                //集合为空返回默认
                .orElseGet(ArrayList::new)
                //创建并行流 相当于多线程无序
                .parallelStream()
                //过滤名字不能为空
                .filter(u -> StringUtils.isNotBlank(u.getRealName()))
                //转成list集合
                .collect(Collectors.toList())
                //遍历
                .forEach(u->{
                    System.out.println(u);
                });
	}
	
	/**
	 * List存放string数据转为大小写
	 */
	private static void test3() {
		List<String> strList = Arrays.asList("a", "b", "d", "s", "n", "a", "s", "c", "d", null);
        //创建并行流
        strList.parallelStream()
                //过滤 非空判断
                .filter(s-> StringUtils.isNotBlank(s))
                //转成大写    toLowerCase转为小写
                .map(String::toUpperCase)
                //遍历
                .forEach(System.out::println);
	}
	
	
	/**
	 * 获取List数据得到一个以逗号分隔的字符串
	 */
	private static void test4() {
		List<String> strList = Arrays.asList("a", "b", "d", "s", "n", "a", "s", "c", "d", "b","");
        String str = strList.parallelStream()
                //过滤条件
                .filter(s -> StringUtils.isNotBlank(s))
                //以逗号分隔数据
                .collect(Collectors.joining(","));
        //打印
        System.out.println(str);
	}
	
	/**
	 * list去重
	 */
	private static void test5() {
		List<String> strList = Arrays.asList("a","b","d","s","n","a","s","c","d", "b");
		//原来集合长度
		System.out.println("list原始的长度"+strList.size());
		// 返回一个去掉重复元素之后的新的lis
		List<String> noRepeatList = strList.stream()
			//去重
			.distinct()
			//转为新集合
			.collect(Collectors.toList());
		
		//新集合长度
		System.out.println("list去重后长度"+noRepeatList.size());

	}

	/**
	 * List存储int数据查找最大值最小值
	 */
	private static void test6() {
	       //创建集合存放int数据
        List<Integer> ints = Stream.of(1,2,4,3,5).collect(Collectors.toList());
        //创建并行流
        int asInt = ints.parallelStream()
                //查找最大值
                .max(Comparator.comparing(i->i))
                //返回最大值
                .get();
        //打印
        System.out.println("最大值:"+asInt);

       //创建集合存放int数据
        List<Integer> ints2 = Stream.of(1,2,4,3,5).collect(Collectors.toList());
        //创建并行流
        int asInt2 = ints2.parallelStream()
                //查找最小值
                .min(Comparator.comparing(i->i))
                //返回最小值
                .get();
        //打印
        System.out.println("最小值:"+asInt2);
        
 		// 集合中最大长度
        List<String> strList = Arrays.asList("a", "b", "d", "s", "n", "yu", "luo", "shuai", "spot", "xhuai");
        int max = strList.stream()
                // 判断条件:长度
                .mapToInt(s -> s.length())
                // 获取判断条件的最大值
                .max()
                // 转成int长度
                .getAsInt();
        //打印最大长度
        System.out.println("集合中最大长度:"+max);
        
                strList.stream()
                //过滤条件 查找元素中的最大值
                .filter(s -> s.length() == max)
                 //转成list集合       
                .collect(Collectors.toList())
                 //遍历打印
                .forEach(s->{
                    System.out.println("集合中最大长度的value为:"+s);
                });

        // 集合中最小长度
        List<String> strList2 = Arrays.asList("a", "b", "d", "s", "nd", "yu", "luo", "shuai");
        //创建顺序流
        int min = strList2.stream()
                //判断条件： 长度
                .mapToInt(s -> s.length())
                //获取最小长度
                .min().getAsInt();
        //打印最小长度
        System.out.println("集合中最小长度为:"+min);
	}
	
	/**
	 * List集合获取int元素的平方
	 */
	private static void test7() {
		 List<Integer> list = Arrays.asList(1, 2, 6, 9);
        //创建一个串行流
        list.stream()
                //取每个元素的平方
                .map(s -> s * s).collect(Collectors.toList())
                //打印
                .forEach(System.out::println);

	}
	
	/**
	 * List返回特定结果
	 */
	private static void test8() {
		//返回特定结果
        List<String> strList = Arrays.asList("a", "b", "c", "d", "e", "f");
        //创建串行流
        strList.stream()
                .skip(2) // 扔掉前面2个元素
                .limit(3) // 返回前3个元素
                //转换成集合
                .collect(Collectors.toList())
                //打印
                .forEach(System.out::println);
	}

	/**
	 * List对int类型数据进行排序
	 */
	private static void test9() {
	   List<Integer> ints = Arrays.asList(5,8,9,4,3,2,7,1,6,2);
        //创建顺序流
        ints.stream()
                //排序规则后面－前面倒序排序
                //排序规则前面－后面正序排序
                .sorted((ln1, ln2) -> (ln1 - ln2)) // 排序
                .distinct()//去除重复元素 可选可不选 不用这个方法重复元素并列
                //转换成集合
                .collect(Collectors.toList())
                //遍历
                .forEach(System.out::println);
	}

	/**
	 * List匹配规则
	 */
	private static void test10() {
	     /**
         * allMatch: Stream 中全部元素符合传入的predicate, 返回true
         * anyMatch: Stream 中只要有一个元素符合传入的predicate, 返回true
         * noneMatch: Stream 中没有一个元素符合传入的predicate, 返回true
         */
        List<String> strList = Arrays.asList("a", "b", "d", "s", "n", "a", "s", "c", "d", "b");
        // 判断集合中有没有c元素, 返回值boolean
        boolean isExits = strList.stream().anyMatch(s -> s.equals("c"));
        //打印 true
        System.out.println(isExits);
        List<String> strList2 = Arrays.asList("a", "b", "d", "s", "n", "a", "s", "c", "d", "");
        // 判断集合是否全不为空
        boolean isFull = strList2.stream().allMatch(s -> s.isEmpty());
        //打印false
        System.out.println(isFull);
        //Stream 中没有一个元素符合传入的predicate, 返回true
        boolean isNotEmpty = strList2.stream().noneMatch(s -> s.isEmpty());
        //打印false
        System.out.println(isNotEmpty);

		
	}

	/**
	 * List存储对象数据按条件进行分组
	 */
	private static void test11() {
		 //创建集合存储user对象
        List<UserInfo> userInfoList = new ArrayList<>();
        UserInfo user = new UserInfo();
        user.setUserId(5L);
        user.setRealName("zs");
        userInfoList.add(user);
        UserInfo user2 = new UserInfo();
        user2.setUserId(3L);
        user2.setRealName("ls");
        userInfoList.add(user2);
        //返回一个map
//        Map<Long, List<UserInfo>> map = userInfoList.parallelStream()
//                //过滤条件 名字不能为空
//                .filter(s -> StringUtils.isNotBlank(s.getRealName()))
//                //使用userId进行分组
//                .collect(groupingBy(UserInfo::getUserId));
//        //遍历打印
//        map.forEach((k,v)->{
//            System.out.println("key:"+k+"  "+"value："+v);
//        });
	}

	/**
	 * 流中的归约用法
	 */
	private static void test12() {
		//创建集合存储user对象
        List<UserInfo> userInfoList = new ArrayList<>();
        UserInfo user = new UserInfo();
        user.setUserId(5L);
        user.setRealName("zs");
        userInfoList.add(user);
        UserInfo user2 = new UserInfo();
        user2.setUserId(3L);
        user2.setRealName("ls");
        userInfoList.add(user2);
        //归约求和
        Optional<Long> reduce = userInfoList.stream()
                //过滤
                .filter(u -> StringUtils.isNotBlank(u.getRealName()))
                //提取userInfo的id
                .map(UserInfo::getUserId)
                //归约求和
                .reduce(Long::sum);
        System.out.println(reduce.get());
        //归约求最大值
        Optional<Long> reduce1 = userInfoList.stream()
                //提取
                .map(UserInfo::getUserId)
                //求最大值
                .reduce(Long::max);
        System.out.println(reduce1.get());
        //归约求最小值
        Optional<Long> reduce2 = userInfoList.stream()
                //提取
                .map(UserInfo::getUserId)
                //求最小值
                .reduce(Long::min);
        System.out.println(reduce2.get());
        //求平均值
        OptionalDouble average = userInfoList.stream()
                //提取
                .mapToLong(UserInfo::getUserId)
                //求平均值
                .average();
        System.out.println(average.getAsDouble());
  		//计数
        long count = userInfoList.stream()
                //提取
                .mapToLong(UserInfo::getUserId)
                //计数
                .count();
        //打印
        System.out.println(count);		
	}

	/**
	 * Java8 summaryStatijstics配合流使用
	 */
	private static void test13() {
		//创建集合存储user对象
        List<UserInfo> userInfoList = new ArrayList<>();
        UserInfo user = new UserInfo();
        user.setUserId(5L);
        user.setRealName("zs");
        userInfoList.add(user);
        UserInfo user2 = new UserInfo();
        user2.setUserId(3L);
        user2.setRealName("ls");
        userInfoList.add(user2);
		//summaryStatijstics使用
        LongSummaryStatistics summaryStatistics = userInfoList.stream()
    			//提取
                .mapToLong(UserInfo::getUserId)
                .summaryStatistics();
        //求最大值
        System.out.println("最大值："+summaryStatistics.getMax());
        //求最小值
        System.out.println("最小值："+summaryStatistics.getMin());
        //求和
        System.out.println("求和："+summaryStatistics.getSum());
        //计数
        System.out.println("计数："+summaryStatistics.getCount());
 		//求平均值
        System.out.println("平均值："+summaryStatistics.getAverage());		
	}

	/**
	 * Java8字符串转字符
	 */
	private static void test14() {
		//字符串转字符数组
        List<String> strList = Arrays.asList("a", "b", "d", "s", "n", "yu", "luo", "shuai", "spot", "xhuai");
       //创建集合存放character元素
        List<Character> newList = new ArrayList<>();
                        //转换为char数组流
        strList.stream().map(String::toCharArray)
                //遍历存放character元素
                .forEach(s->{
                    //遍历每个元素
                    for (char c : s) {
                        //存放
                        newList.add(c);
                    }
                });
        //打印
        newList.stream().forEach(System.out::println);
	 //第二种写法
	 strList.stream().map(String::toCharArray)
                //对转换的char[]数组整合
                .flatMapToInt(chars -> CharBuffer.wrap(chars).chars())
                //转换为char类型
                .mapToObj(e -> (char) e)
                //转为集合存储
                .collect(Collectors.toList())
                //遍历
                .forEach(System.out::println);
		
	}
	
}
